package base.collection_demo.demo03;

import org.junit.Test;

import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.TreeSet;

/**
 *
 */
public class Client {

    /**
     * TreeSet
     * 同时提供了TreeSet中对象自然排序 和 在构造Set时给TreeSet<Comparator>提供外部比较器Comparator，比较器优先级最高演示
     */
    // TreeSet存储的对象需要具备自然排序能力
    @Test
    public void testCase1_1(){
        Person p1 = new Person("zhangsan", 18);
        Person p2 = new Person("lisi", 20);
        Person p3 = new Person("tianqi", 19);
        Person p4 = new Person("lisi", 20);

        // Set集合中存储的Person对象没有定义自然排序
        TreeSet<Person> set = new TreeSet<>();
        set.add(p1);//报错，Person 不具备自然排序能力（没有实现 Comparable 接口）
        set.add(p2);
        set.add(p3);
        set.add(p1);

        for (Person person : set) {
            System.out.println(person);
        }
    }

    // 对象具备自然排序能力
    @Test
    public void testCase1_2(){
        PersonComparable p1 = new PersonComparable("zhangsan", 18);
        PersonComparable p2 = new PersonComparable("lisi", 20);
        PersonComparable p3 = new PersonComparable("tianqi", 19);
        PersonComparable p4 = new PersonComparable("lisi", 20);

        // Set集合中存储的 PersonComparable 对象定义了自然排序
        TreeSet<PersonComparable> set = new TreeSet<>();
        set.add(p1);
        set.add(p2);
        set.add(p3);
        set.add(p1);//重复存了 p1，与 hashCode()和equals()方法根本没有关系，只看compareTo()
        set.add(p4);

        for (PersonComparable person : set) {//set中存入了5个对象,其中p1重复存入了2遍
            System.out.println(person);
        }
    }

    // 对象具备自然排序能力同时，给TreeSet提供了一个外部比较器
    @Test
    public void testCase1_3(){
        PersonComparable p1 = new PersonComparable("zhangsan", 18);
        PersonComparable p2 = new PersonComparable("lisi", 20);
        PersonComparable p3 = new PersonComparable("tianqi", 19);
        PersonComparable p4 = new PersonComparable("lisi", 20);

        /*
         * 外部比较器的compare()方法返回0，表示往TreeSet集合中存入的所有对象都是相等的，由Set集合不存储相等对象的规约 +
         * 外部比较器优先的原则，导致该测试案例只会存入一个对象（即使对象自然排序的compareTo()返回1表示按照存入顺序存入）。
         */
        MyComparator<PersonComparable> comparator = new MyComparator<>();
        TreeSet<PersonComparable> set = new TreeSet<>(comparator);
        set.add(p1);
        set.add(p2);
        set.add(p3);
        set.add(p4);

        for (PersonComparable p : set) {//set中只有一个对象
            System.out.println(p);
        }
    }


    // TreeSet是带排序的。
    @Test
    public void testCase1_4(){
        Person p1 = new Person("zhangsan", 18);
        Person p2 = new Person("lisi", 20);
        Person p3 = new Person("tianqi", 19);
        Person p4 = new Person("lisi", 20);

        TreeSet<Person> set = new TreeSet<>(new Comparator<Person>() {
            // 重写的逻辑要保证Set集合的规约-即满足存入的对象不重复。
            @Override
            public int compare(Person o1, Person o2) {
               return o1.getName().compareTo(o2.getName())==0?
                       (o1.getAge().compareTo(o2.getAge())):o1.getName().compareTo(o2.getName());
            }
        });

        set.add(p1);
        set.add(p2);
        set.add(p3);
        set.add(p4);

        for (Person person : set) {
            System.out.println(person);
        }
    }

    /**
     * LinkedHashSet 有序，存入取出顺序一致。
     */
    @Test
    public void testCase2_1(){
        LinkedHashSet<String> set = new LinkedHashSet<>();
        set.add("zhangsan");
        set.add("lisi");
        set.add("wangwu");
        set.add("zhaoliu");
        set.add("tianqi");
        set.add("lisi");// 遵循不重复存入规约

        for (String s : set) {//存入5个对象
            System.out.println(s);
        }
    }

    // HashSet 规约的实现是通过hashCode() 和 equals()方法来约束的
    @Test
    public void testCase3_1(){
        Person p1 = new Person("zhangsan", 18);
        Person p2 = new Person("lisi", 20);
        Person p3 = new Person("tianqi", 19);
        Person p4 = new Person("lisi", 20);
        Person p5 = new Person("ww", 20);

        HashSet<Person> set = new HashSet<>();
        set.add(p1);
        set.add(p2);
        set.add(p3);
        set.add(p4);
        set.add(p5);

        for (Person person : set) {
            System.out.println(person);
        }
    }


}
